package com.irain.pp.tool.mybatis.mgmt;

import com.irain.pp.tool.annotation.NotNull;
import com.irain.pp.tool.mybatis.mapper.PpDataMapper;
import com.irain.pp.tool.api.data.DataObject;
import com.irain.pp.tool.mybatis.mapper.PpRecordMapper;
import com.irain.pp.tool.mybatis.model.BaseRecordDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;

/**
 * @author WangYanPeng
 * @date 2017/10/19 10:06
 */
public abstract class BaseDataManagerImpl<DO extends DataObject> extends BaseManagerImpl<DO> implements BaseManager<DO> {

    @Autowired
    private PpDataMapper<DO> mapper;


    /*------------- select for update -----------*/


    public DO selectByIdForUpdate(Long id) {
        if (id == null) return null;
        return mapper.selectByPrimaryKeyForUpdate(id);
    }

    @NotNull
    public List<DO> selectForUpdate(@NotNull DO condition) {
        Assert.notNull(condition, notNullError("condition"));
        return mapper.selectForUpdate(condition);
    }

    public DO selectOneForUpdate(@NotNull DO condition) {
        Assert.notNull(condition, notNullError("condition"));
        return mapper.selectOneForUpdate(condition);
    }


    /*------------- select by example -----------*/

    @NotNull
    public List<DO> selectByExample(@NotNull Example example) {
        Assert.notNull(example, notNullError("example"));
        return mapper.selectByExample(example);
    }

    public int selectCountByExample(@NotNull Example example) {
        Assert.notNull(example, notNullError("example"));
        return mapper.selectCountByExample(example);
    }


    /*------------- update -----------*/

    public void updateById(@NotNull DO record) {
        Assert.notNull(record.getId(), notNullError("id"));
        record.setGmtModified(new Date());
        final int count = mapper.updateByPrimaryKey(record);
        Assert.isTrue(count == 1, updateCountError(count));
    }

    public void updateByIdSelective(@NotNull DO record) {
        Assert.notNull(record.getId(), notNullError("id"));
        record.setGmtModified(new Date());
        final int count = mapper.updateByPrimaryKeySelective(record);
        Assert.isTrue(count == 1, updateCountError(count));
    }


    /*------------- update by example -----------*/

    public void updateOneByExample(@NotNull DO record, @NotNull Example example) {
        Assert.notNull(record.getId(), notNullError("id"));
        Assert.notNull(example, notNullError("example"));
        int count = mapper.updateByExample(record, example);
        Assert.isTrue(count == 1, updateCountError(count));
    }

    public void updateOneByExampleSelective(@NotNull Long id,@NotNull DO record, @NotNull Example example) {
        Assert.notNull(id, notNullError("id"));
        Assert.notNull(record, notNullError("record"));
        Assert.notNull(example, notNullError("example"));
        example.and().andEqualTo(DataObject.ID,id);
        int count = mapper.updateByExampleSelective(record, example);
        Assert.isTrue(count == 1, updateCountError(count));
    }

    protected int updateByExampleSelective(@NotNull DO record, @NotNull Example example, Integer checkNum) {
        Assert.notNull(record, notNullError("record"));
        Assert.notNull(example, notNullError("example"));
        int count = mapper.updateByExampleSelective(record, example);
        if (checkNum != null) {
            Assert.isTrue(checkNum == count, updateCountError(count));
        }
        return count;
    }


    /*------------- insert -----------*/

    @NotNull
    public void insert(@NotNull DO dataObject) {
        dataObject.setGmtCreated(new Date());
        dataObject.setGmtModified(dataObject.getGmtCreated());
        final int count = mapper.insert(dataObject);
        Assert.isTrue(count == 1, insertCountError(count));
    }


    /*------------- delete -----------*/

    public boolean deleteById(@NotNull Long id) {
        Assert.notNull(id, notNullError("id"));
        final int count = mapper.deleteByPrimaryKey(id);
        Assert.isTrue(count < 2, deleteCountError(count));
        return count == 1;
    }

    protected int deleteByExample(@NotNull Object example) {
        Assert.notNull(example, notNullError("example"));
        return mapper.deleteByExample(example);
    }

    /*------------- record --------------*/

    protected  <RDO extends BaseRecordDO> void insertRecord(PpRecordMapper<RDO> mapper, RDO record) {
        record.setGmtCreated(new Date());
        int insert = mapper.insert(record);
        Assert.isTrue(insert == 1, insertCountError(insert));
    }

}
